﻿using LxBasic;
using LxLESS;

namespace LxCore
{
    public class FvMesh : JsObject
    {
        public FvZoneList Zones { get; set; } = new();
        public FvJointList Joints { get; set; } = new();
        public LESSSetting LessSetting { get; set; } = new LESSSetting();
        public void CheckCreate()
        {
            MultiThreads.RunParallelTask((threadInfo) =>
            {
                for (int i1 = threadInfo.CurrentThreadID; i1 < Zones.Count; i1 += threadInfo.TotalThreadsCount)
                {
                    Zones[i1].CheckCreate();
                }
            });
            MultiThreads.RunParallelTask((threadInfo) =>
            {
                for (int i1 = threadInfo.CurrentThreadID; i1 < Joints.Count; i1 += threadInfo.TotalThreadsCount)
                {
                    Joints[i1].CheckCreate();
                }
            });
            //foreach (var z in LxSim.Sim.Mesh.Zones)
            //{
            //    z.CheckCreate();
            //}
            //foreach (var c in LxSim.Sim.Mesh.Joints)
            //{
            //    c.CheckCreate();
            //}
        }

        public void Report()
        {
#if DEBUG
            foreach (var z in Zones)
            {
                LxLog.Info(string.Format($"zone:{z.Name},{z.Inner.CellIdx},{z.Inner.FaceIdx}"));
                foreach (var t in z.Bounds)
                {
                    LxLog.Info(string.Format($"bound:{t.Name},{t.CellIdx},{t.FaceIdx}"));
                }
            }
            foreach (var z in Zones)
            {
                LxLog.Info(string.Format($"zone:{z.Name},{z.Inner.CellIdx},{z.Inner.FaceIdx}"));
                foreach (var t in z.Bounds)
                {
                    LxLog.Info(string.Format($"bound:{t.Name},{t.CellIdx},{t.FaceIdx}"));
                }
            }
#else
            //foreach (var z in Zones)
            //{
            //    LxConsole.Calc(string.Format($"zone:{z.Name},{z.InnerIndex.CellIDs.GetCount()}"));
            //    StringBuilder strb = new StringBuilder("bound:");                
            //    foreach (var t in z.BoundThreads)
            //    {
            //        strb.Append(t.Name);
            //        strb.Append(",");
            //    }
            //    strb.Replace(',', '.', strb.Length - 1, 1);
            //    LxConsole.Calc(strb.ToString());
            //}
#endif
            Bound3d b = new Bound3d();
            foreach (var z in Zones)
            {
                foreach (var p in z.Nodes)
                {
                    b.Include(p);
                }
            }
            LxLog.Calc(b.ToString());
        }

        public void ReorderCellFaceId()
        {

        }
        public void CheckTopology()
        {
            foreach (var z in Zones)
            {
                z.CheckTopology();
            }
        }

        public void AddMesh(FvMesh mesh)
        {
            foreach (var z in mesh.Zones)
            {
                Zones.Add(z);
            }
            foreach (var c in mesh.Joints)
            {
                Joints.Add(c);
            }
            CheckCreate();
            CheckTopology();
        }


        public override void FromJsonKV(string key, IJsonReader jsReader)
        {
            switch (key)
            {
                case nameof(Zones): jsReader.ReadList(Zones, t => new FvZone()); break;
                case nameof(Joints): jsReader.ReadList(Joints, t => new FvJoint(this)); break;
                default: base.FromJsonKV(key, jsReader); break;
            }
        }
        public override void ToJsonKV(IJsonWriter jsWriter)
        {
            base.ToJsonKV(jsWriter);
            jsWriter.WriteList(nameof(Zones), Zones);
            jsWriter.WriteList(nameof(Joints), Joints);
        }
        public class LESSSetting
        {
            public LESSSetting()
            {
                this.MaxCoarseLevel = 50;
            }
            public int AMGGroupCount = 4;
            public int MaxCoarseLevel { get => AMGGlobal.MaxLevel; set => AMGGlobal.MaxLevel = value; }
        }
    }
}
//private void CreateLESSZone()
//{
//    if (LxSim.Sim.Mesh.Zones.Count <= 0) return;
//    AMGGlobal.MaxLevel = LessSetting.MaxCoarseLevel;
//    foreach (var z in LxSim.Sim.Mesh.Zones)
//    {
//        if (z.LESSZone == null)
//        {
//            z.LESSZone = new LESSZone();
//            z.LESSZone.CheckCreate(z, LessSetting.AMGGroupCount, LessSetting.IsBiCGOnlySupprotAMG ? -1 : z.InnCells.Length, z.InnCellInnFaceShare, z.InnCellBouFaceShare);
//        }
//    }
//    foreach (var c in LxSim.Sim.Mesh.Joints)
//    {
//        if (c.LESSJoint == null)
//        {
//            c.LESSJoint = new LESSJoint();
//            c.LESSJoint.CheckCreate(c, c.OZone.LESSZone, c.OBound.ID,
//                c.NZone.LESSZone, c.NBound.ID);
//        }
//    }
//}
//if (LessSet.IsBiCGOnlySupprotAMG)
//{
//    foreach (FvZone z in Zones)
//    {
//        z.LESSZone.CreateBiCGZone(z.LESSZone.MGZones[0].InnCells.Length, z.InnCellInnFaceShare, z.InnCellBouFaceShare);
//    }
//}
//else
//{
//    foreach (FvZone z in Zones)
//    {
//        z.LESSZone.CreateBiCGZone(z.InnCells.Length, z.InnCellInnFaceShare, z.InnCellBouFaceShare);
//    }
//}
//MGMeshCreator mgmaker = new MGMeshCreator();
//mgmaker.Create(LessSet.MaxCoarseLevel, LessSet.AMGGroupCount, Zones[0].Cells.Length);